import { ipcRenderer, contextBridge } from 'electron'

// 定义所有合法的IPC通道
const CRUD_CHANNELS = {
  PATIENT: [
    'create-patient',
    'read-patients',
    'update-patient',
    'delete-patient',
    'search-patients'
  ],
  USER: [
    'create-user',
    'read-users',
    'update-user',
    'delete-user',
    'search-users',
    'change-user-password',
    'upload-avatar'
  ],
  EVENT: [
    'user-updated',
    'user-created',
    'patient-updated',
    'patient-created'
  ]
};

// 安全地暴露 IPC 方法给渲染进程
contextBridge.exposeInMainWorld('electronAPI', {
  ipcRenderer: {
    // 通用发送方法
    send: (channel: string, ...args: any[]) => {
      const allValidChannels = [
        ...CRUD_CHANNELS.PATIENT,
        ...CRUD_CHANNELS.USER
      ];
      if (allValidChannels.includes(channel)) {
        ipcRenderer.send(channel, ...args);
      } else {
        console.warn(`Blocked attempt to send via invalid channel: ${channel}`);
      }
    },

    // 通用调用方法
    invoke: (channel: string, ...args: any[]) => {
      const allValidInvokeChannels = [
        ...CRUD_CHANNELS.PATIENT.filter(c => c !== 'search-patients'),
        ...CRUD_CHANNELS.USER.filter(c => c !== 'search-users')
      ];

      if (allValidInvokeChannels.includes(channel)) {
        return ipcRenderer.invoke(channel, ...args);
      }
      return Promise.reject(new Error(`Invalid channel: ${channel}`));
    },

    // 专用搜索方法（保持原有搜索功能）
    searchPatients: (keyword: string) => {
      return ipcRenderer.invoke('search-patients', keyword);
    },

    // 新增用户搜索方法
    searchUsers: (keyword: string) => {
      return ipcRenderer.invoke('search-users', keyword);
    },

    // 监听事件（合并用户和患者事件）
    on: (channel: string, listener: (...args: any[]) => void) => {
      if (CRUD_CHANNELS.EVENT.includes(channel)) {
        const subscription = (_event: any, ...args: any[]) => listener(...args);
        ipcRenderer.on(channel, subscription);

        return () => {
          ipcRenderer.removeListener(channel, subscription);
        };
      }
      console.warn(`Attempt to listen to invalid channel: ${channel}`);
    },

    // 移除监听器
    removeAllListeners: (channel: string) => {
      if (CRUD_CHANNELS.EVENT.includes(channel)) {
        ipcRenderer.removeAllListeners(channel);
      }
    }
  }
});

// // 从渲染进程发送消息到主进程
    // send: (channel: string, ...args: any[]) => {
    //     const validChannels = ['create-patient', 'read-patients', 'update-patient', 'delete-patient'];
    //     if (validChannels.includes(channel)) {
    //       ipcRenderer.send(channel, ...args);
    //   }
    // },
    // // 添加搜索方法
    // searchPatients: (keyword: string) => {
    //   return ipcRenderer.invoke('search-patients', keyword);
    // },
    // // 从渲染进程调用主进程方法并等待结果
    // invoke: (channel: string, ...args: any[]) => {
    //   const validChannels = ['create-patient', 'read-patients', 'update-patient', 'delete-patient'];
    //   if (validChannels.includes(channel)) {
    //     return ipcRenderer.invoke(channel, ...args);
    //   }
    //   return Promise.reject(new Error(`Invalid channel: ${channel}`));
    // },
    //
    // // 监听主进程发送的消息
    // on: (channel: string, listener: (...args: any[]) => void) => {
    //   const validChannels = ['patient-updated', 'patient-created'];
    //   if (validChannels.includes(channel)) {
    //     // 过滤掉 event 参数，避免暴露不必要的 API
    //     const subscription = (_event: any, ...args: any[]) => listener(...args);
    //     ipcRenderer.on(channel, subscription);
    //
    //     // 返回取消监听的函数
    //     return () => {
    //       ipcRenderer.removeListener(channel, subscription);
    //     };
    //   }
    // },
    //
    // // 移除监听器
    // removeAllListeners: (channel: string) => {
    //   ipcRenderer.removeAllListeners(channel);
    // }




// --------- Preload scripts loading ---------
function domReady(condition: DocumentReadyState[] = ['complete', 'interactive']) {
  return new Promise(resolve => {
    if (condition.includes(document.readyState)) {
      resolve(true)
    } else {
      document.addEventListener('readystatechange', () => {
        if (condition.includes(document.readyState)) {
          resolve(true)
        }
      })
    }
  })
}

const safeDOM = {
  append(parent: HTMLElement, child: HTMLElement) {
    if (!Array.from(parent.children).find(e => e === child)) {
      return parent.appendChild(child)
    }
  },
  remove(parent: HTMLElement, child: HTMLElement) {
    if (Array.from(parent.children).find(e => e === child)) {
      return parent.removeChild(child)
    }
  },
}

/**
 * https://tobiasahlin.com/spinkit
 * https://connoratherton.com/loaders
 * https://projects.lukehaas.me/css-loaders
 * https://matejkustec.github.io/SpinThatShit
 */
function useLoading() {
  const className = `loaders-css__square-spin`
  const styleContent = `
@keyframes square-spin {
  25% { transform: perspective(100px) rotateX(180deg) rotateY(0); }
  50% { transform: perspective(100px) rotateX(180deg) rotateY(180deg); }
  75% { transform: perspective(100px) rotateX(0) rotateY(180deg); }
  100% { transform: perspective(100px) rotateX(0) rotateY(0); }
}
.${className} > div {
  animation-fill-mode: both;
  width: 50px;
  height: 50px;
  background: #fff;
  animation: square-spin 3s 0s cubic-bezier(0.09, 0.57, 0.49, 0.9) infinite;
}
.app-loading-wrap {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #282c34;
  z-index: 9;
}
    `
  const oStyle = document.createElement('style')
  const oDiv = document.createElement('div')

  oStyle.id = 'app-loading-style'
  oStyle.innerHTML = styleContent
  oDiv.className = 'app-loading-wrap'
  oDiv.innerHTML = `<div class="${className}"><div></div></div>`

  return {
    appendLoading() {
      safeDOM.append(document.head, oStyle)
      safeDOM.append(document.body, oDiv)
    },
    removeLoading() {
      safeDOM.remove(document.head, oStyle)
      safeDOM.remove(document.body, oDiv)
    },
  }
}

// ----------------------------------------------------------------------

const { appendLoading, removeLoading } = useLoading()
domReady().then(appendLoading)

window.onmessage = (ev) => {
  ev.data.payload === 'removeLoading' && removeLoading()
}

setTimeout(removeLoading, 4999)